package com.jxmcloud.business.cut.service.impl.user;

import cn.hutool.core.util.ObjectUtil;
import com.jxmcloud.business.cut.constants.CutConstants;
import com.jxmcloud.business.cut.constants.CutSaveKey;
import com.jxmcloud.business.cut.dtoCommon.BagInfoDto;
import com.jxmcloud.business.cut.json.DataConfigService;
import com.jxmcloud.business.cut.json.DataConfigStartLoader;
import com.jxmcloud.business.cut.model.database.DBUserFlowInfo;
import com.jxmcloud.business.cut.service.database.IUserFlowDBService;
import com.jxmcloud.business.cut.service.database.IUserInviteSuccessDBService;
import com.jxmcloud.business.cut.service.user.*;
import com.jxmcloud.business.cut.util.MyTool;
import com.jxmcloud.business.cut.vo.UserOrderTranVo;
import com.jxmcloud.business.cut.vo.json.ConfigEventVo;
import com.jxmcloud.business.cut.vo.json.ConfigProgressVo;
import com.jxmcloud.business.cut.vo.json.ConfigStartVo;
import com.jxmcloud.business.cut.vo.user.PlayerInfoVo;
import com.jxmcloud.business.cut.vo.user.UserCashDetailItemVo;
import com.jxmcloud.business.cut.vo.user.UserFlowVo;
import com.xlcloud.platform.api.config.Constant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

@Slf4j
@Service
public class UserFlowServiceImpl implements IUserFlowService {
    @Autowired
    private IUserFlowDBService userFlowDBService;
    @Resource
    private DataConfigService dataConfigService;
    @Resource
    private IUserBagService userBagService;
    @Resource
    private IUserCashDetailListService userCashDetailListService;
    @Resource
    private DataConfigStartLoader dataConfigStartLoader;
    @Resource
    private IUserDrawTurnService userDrawTurnService;
    @Resource
    private IUserActivityService userActivityService;
    @Resource
    private IUserInviteSuccessDBService userInviteSuccessDBService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveToDb(PlayerInfoVo player, String key) {
        if (key.equals(CutSaveKey.USER_FLOW)) {
            DBUserFlowInfo info = new DBUserFlowInfo();
            info.setUid(player.getBase().getUid());
            info.setActivityId(player.getActivity().getActivityId());
            info.setStepId(player.getFlowInfo().getStepId());
            info.setPreId(player.getFlowInfo().getPreId());
            info.setReviveStepId(player.getFlowInfo().getReviveStepId());

            userFlowDBService.updateData(info);
        }

        return true;
    }

    @Override
    public boolean loadFromDb(PlayerInfoVo player, Integer uid) {
        DBUserFlowInfo dbUserFlowInfo = userFlowDBService.selectOne(uid, player.getActivity().getActivityId());
        if (ObjectUtil.isNotNull(dbUserFlowInfo)) {
            UserFlowVo flowInfo = player.getFlowInfo();
            flowInfo.setUid(dbUserFlowInfo.getUid());
            flowInfo.setStepId(dbUserFlowInfo.getStepId());
            if (MyTool.isTure(dbUserFlowInfo.getPreId())) {
                flowInfo.setPreId(dbUserFlowInfo.getPreId());
            }
            if (MyTool.isTure(dbUserFlowInfo.getReviveStepId())) {
                flowInfo.setReviveStepId(dbUserFlowInfo.getReviveStepId());
            }

            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(PlayerInfoVo player, Integer uid) {
        DBUserFlowInfo dbUserFlowInfo = new DBUserFlowInfo();
        dbUserFlowInfo.setUid(uid);
        dbUserFlowInfo.setActivityId(player.getActivity().getActivityId());
        ConfigStartVo configStartVo = dataConfigStartLoader.getConfigById(player.getActivity().getStartId());
        dbUserFlowInfo.setStepId(configStartVo.getNext());
        boolean b = userFlowDBService.insertIntoData(dbUserFlowInfo);
        if (b) {
            UserFlowVo flowInfo = player.getFlowInfo();
            flowInfo.setUid(dbUserFlowInfo.getUid());
            flowInfo.setStepId(dbUserFlowInfo.getStepId());
            return true;
        }
        return false;
    }

    @Override
    public boolean checkEventValid(PlayerInfoVo player, Integer nowStep, Integer checkEventId) {
        // 检测步骤接口
        ConfigProgressVo progressConfig = dataConfigService.getConfigProgressConfig(nowStep);
        if (ObjectUtil.isNull(progressConfig)) {
            return false;
        }
        //
        Integer[] startEvent = progressConfig.getStartEvent();
        if (ObjectUtil.isNotNull(startEvent)) {
            // 判断界面事件
            for (int i = 0; i < startEvent.length; ++i) {
                if (startEvent[i].equals(checkEventId)) {
                    return true;
                }
            }
        }
        Integer[] timeEvent = progressConfig.getTimeEvent();
        if (ObjectUtil.isNotNull(timeEvent)) {
            // 判断显示事件
            for (int i = 1; i < timeEvent.length; ++i) {
                if (timeEvent[i].equals(checkEventId)) {
                    return true;
                }
            }
        }
        // 关闭事件
        Integer[] closeEvent = progressConfig.getCloseEvent();
        if (ObjectUtil.isNotNull(closeEvent)) {
            for (int i = 0; i < closeEvent.length; ++i) {
                if (closeEvent[i].equals(checkEventId)) {
                    return true;
                }
            }
        }
        // 点击事件
        Integer[] clickEvent = progressConfig.getClickEvent();
        if (ObjectUtil.isNotNull(clickEvent)) {
            for (int i = 0; i < clickEvent.length; ++i) {
                if (clickEvent[i].equals(checkEventId)) {
                    return true;
                }
            }
        }
        // 分享事件
        Integer[] shareEvent = progressConfig.getShareEvent();
        if (ObjectUtil.isNotNull(shareEvent)) {
            for (int i = 0; i < shareEvent.length; ++i) {
                if (shareEvent[i].equals(checkEventId)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean runEvent(PlayerInfoVo player, Integer eventId) {
        // 判断事件
        ConfigEventVo eventConfig = dataConfigService.getConfigEventConfig(eventId);
        if (ObjectUtil.isNull(eventConfig)) {
            return false;
        }
        // 判断事件是否满足条件
        Integer progressId = eventConfig.getProgressId();
        return this.enterNextProgress(player, progressId);
    }

    @Override
    public boolean enterNextProgress(PlayerInfoVo player, Integer progressId) {
        UserFlowVo flowInfo = player.getFlowInfo();
        Integer oldProgressId = flowInfo.getStepId();
        ConfigProgressVo progressConfig = dataConfigService.getConfigProgressConfig(progressId);
        if (ObjectUtil.isNull(progressConfig)) {
            return false;
        }
        flowInfo.setPreId(oldProgressId);
        flowInfo.setStepId(progressId);
        // 判断是否有触发标题  没有触发标题就是实物
        if (ObjectUtil.isNull(progressConfig.getOrderTrans())) {
            // 创建订单
            userCashDetailListService.makeCashDetailByProgressId(player, progressId);
        } else {
            userCashDetailListService.makeOrderCashDetailByProgressId(player, progressId);
        }
        // 检测轮盘初始化
        userDrawTurnService.checkTurnRelease(player, progressConfig.getRoundType());
        player.getMaster().getSaveList().add(CutSaveKey.USER_FLOW);
        return true;
    }

    @Override
    public boolean revertRunEvent(PlayerInfoVo player, Integer eventId) {
        // 判断事件
        ConfigEventVo eventConfig = dataConfigService.getConfigEventConfig(eventId);
        if (ObjectUtil.isNull(eventConfig)) {
            return false;
        }
        // 判断事件是否满足条件
        Integer progressId = eventConfig.getProgressId();
        return this.revertEnterNextProgress(player, progressId);
    }

    @Override
    public boolean revertEnterNextProgress(PlayerInfoVo player, Integer progressId) {
        UserFlowVo flowInfo = player.getFlowInfo();
        Integer oldProgressId = flowInfo.getStepId();
        ConfigProgressVo progressConfig = dataConfigService.getConfigProgressConfig(progressId);
        if (ObjectUtil.isNull(progressConfig)) {
            return false;
        }
        flowInfo.setPreId(oldProgressId);
        flowInfo.setStepId(progressId);
        // 判断是否有触发标题  没有触发标题就是实物
        if (ObjectUtil.isNull(progressConfig.getOrderTrans())) {
            // 创建订单
            userCashDetailListService.revertMakeCashDetailByProgressId(player, progressId);
        } else {
            userCashDetailListService.revertMakeOrderCashDetailByProgressId(player, progressId);
        }
        // 检测轮盘初始化
        userDrawTurnService.checkTurnRelease(player, progressConfig.getRoundType());
        player.getMaster().getSaveList().add(CutSaveKey.USER_FLOW);
        return true;
    }

    @Override
    public BagInfoDto calcProgressAward(PlayerInfoVo player, Integer progressId) {
        ConfigProgressVo progressConfig = dataConfigService.getConfigProgressConfig(progressId);
        if (ObjectUtil.isNull(progressConfig)) {
            return null;
        }
        Integer[] awards = progressConfig.getAward();
        if (ObjectUtil.isNull(awards)) {
            return null;
        }
        switch (awards.length) {
            case 2: {
                BagInfoDto item = new BagInfoDto();
                item.setId(awards[0]);
                item.setCount(awards[1]);
                return item;
            }
            case 3: {
                BagInfoDto item = new BagInfoDto();
                item.setId(awards[0]);
                Integer maxCount = awards[1] + awards[2];
                int random = new Random().nextInt(maxCount);
                Integer randomCount = (Integer) random - awards[1];
                item.setCount(randomCount);
                return item;
            }
            case 4: {
                BagInfoDto item = new BagInfoDto();
                item.setId(awards[0]);
                Integer maxCount = awards[1] + awards[2];
                int random = new Random().nextInt(maxCount);
                Integer itemCount = userBagService.getItemCount(player, awards[0]);
                if (itemCount >= awards[3]) {
                    return null;
                } else if (itemCount + random >= awards[3]) {
                    random = awards[3] - itemCount;
                }
                Integer randomCount = (Integer) random - awards[1];
                item.setCount(randomCount);
                return item;
            }
            default: {
                return null;
            }
        }
    }

    @Override
    public boolean checkFlowEvent(PlayerInfoVo player, Integer eventId) {
        ConfigEventVo eventConfig = dataConfigService.getConfigEventConfig(eventId);
        if (ObjectUtil.isNull(eventConfig)) {
            return false;
        }
        // 是否是打开事件
        if (!eventConfig.getEvent().equals(1)) {
            return false;
        }
        if (ObjectUtil.isNull(eventConfig.getCondition())) {
            return true;
        }
        int caseId = eventConfig.getCondition();
        switch (caseId) {
            // 有购物
            case CutConstants.CONDITION_HAS_SHOP: {
                if (player.getUserOrderListVo().getUserOrderList().size() > 0) {
                    return true;
                }
                return false;
            }
            // 没有购物
            case CutConstants.CONDITION_NO_SHOP: {
                if (player.getUserOrderListVo().getUserOrderList().size() > 0) {
                    return false;
                }
                return true;
            }
            // 有未转化的
            case CutConstants.CONDITION_HAS_NEW_ORDER: {
                List<UserOrderTranVo> allOrder = player.getUserOrderListVo().getUserOrderList();
                HashMap<String, UserCashDetailItemVo> hashOrder = player.getUserCashDetailVo().getOrderList();
                for (UserOrderTranVo userOrderTranVo : allOrder) {
                    UserCashDetailItemVo order = hashOrder.get(userOrderTranVo.getOrderId() + Constant.LINE_XHX + userOrderTranVo.getSpecId());
                    if (ObjectUtil.isNull(order)) {
                        return true;
                    }
                }
                return false;
            }
            // 道具高于
            case CutConstants.CONDITION_GREATER_ITEM: {
                Integer[] item = eventConfig.getParam();
                Integer itemCount = userBagService.getItemCount(player, item[0]);
                if (itemCount > item[1]) {
                    return true;
                }
                return false;
            }
            case CutConstants.CONDITION_LESS_ITEM: {
                Integer[] item = eventConfig.getParam();
                Integer itemCount = userBagService.getItemCount(player, item[0]);
                if (itemCount < item[1]) {
                    return true;
                }
                return false;
            }
            // 能否复活
            case CutConstants.CONDITION_CAN_RELIVE: {
                // 当前是否处于复活阶段
                Integer reviveStepId = player.getFlowInfo().getReviveStepId();
                return MyTool.isTure(reviveStepId);
            }
            // 邀请好友数
            case CutConstants.CONDITION_INVITE_COUNT: {
                Integer[] item = eventConfig.getParam();
                Integer inviteCount = player.getActivity().getNewUserCount();
                if (inviteCount >= item[1]) {
                    return true;
                }
                return false;
            }
            // 剩余邀请新用户数是否为0
            case CutConstants.CONDITION_LEFT_INVITE_NEWER_IS_0: {
                return userActivityService.isFinishInviteAllNewer(player);
            }
            default: {
                return true;
            }
        }
    }

    @Override
    public void refreshFlowData(PlayerInfoVo player) {
        Integer startId = player.getActivity().getStartId();
        ConfigStartVo startConfig = dataConfigService.getConfigStartConfig(startId);
        if (ObjectUtil.isNull(startConfig)) {
            return;
        }
        player.getFlowInfo().setPreId(0);
        player.getFlowInfo().setReviveStepId(0);
        player.getFlowInfo().setStepId(startConfig.getNext());
        player.getMaster().getSaveList().add(CutSaveKey.USER_FLOW);
    }

    @Override
    public void updateReviveStepId(PlayerInfoVo player, Integer reviveStepId) {
        player.getFlowInfo().setReviveStepId(reviveStepId);
        player.getMaster().getSaveList().add(CutSaveKey.USER_FLOW);
    }

    /**
     * 回到复活前步骤
     *
     * @param player
     */
    @Override
    public void backToReviveStep(PlayerInfoVo player) {
        Integer reviveStepId = player.getFlowInfo().getReviveStepId();
        if (MyTool.isTure(reviveStepId)) {
            Integer beforeStepId = player.getFlowInfo().getStepId();
            player.getFlowInfo().setPreId(beforeStepId);
            player.getFlowInfo().setStepId(reviveStepId);
            player.getFlowInfo().setReviveStepId(0);
            player.getMaster().getSaveList().add(CutSaveKey.USER_FLOW);
        } else {
            log.error("回到复活前步骤失败，reviveStepId为空");
        }
    }

    @Override
    public void resetFlow(PlayerInfoVo player) {

    }

    @Override
    public boolean isInRevive(PlayerInfoVo player) {
        return MyTool.isTure(player.getFlowInfo().getReviveStepId());
    }

    @Override
    public String testEnterLiveStepErr(PlayerInfoVo player) {
        Integer startId = player.getActivity().getStartId();
        ConfigStartVo startConfig = dataConfigService.getConfigStartConfig(startId);
        if (ObjectUtil.isNull(startConfig)) {
            return "开局配置错误";
        }
        Integer liveStepId = startConfig.getNewersFitEnterLiveStep();
        if (ObjectUtil.isNull(liveStepId)) {
            return "开局配置错误~";
        }
        // 要进入直播, 判断邀请新人数是否满足
        if (player.getFlowInfo().getStepId().equals(liveStepId)) {
            boolean isFinish = userActivityService.isFinishInviteAllNewer(player);
            if (!isFinish) {
                return "邀请新人数不足";
            }
        }
        return "";
    }
}
